add `overflow-checks` field to profiles
authorNathan Froyd <froydnj@gmail.com>
Fri, 7 Apr 2017 16:32:42 +0000 (12:32 -0400)
committerNathan Froyd <froydnj@gmail.com>
Fri, 14 Apr 2017 20:44:45 +0000 (16:44 -0400)
...and pass `-C overflow-checks` to the compiler when necessary.

Fixes #2262.

src/cargo/core/manifest.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/toml.rs
tests/build.rs
tests/test.rs

index ad9a129aff4e33e1d613a38322229dd3bc1d8e3d..de18731defd808651abe9bf8aeb6686c8d706672 100644 (file)
@@ -145,6 +145,7 @@ pub struct Profile {
     pub rustdoc_args: Option<Vec<String>>,
     pub debuginfo: Option<u32>,
     pub debug_assertions: bool,
+    pub overflow_checks: bool,
     #[serde(skip_serializing)]
     pub rpath: bool,
     pub test: bool,
@@ -528,6 +529,7 @@ impl Profile {
         Profile {
             debuginfo: Some(2),
             debug_assertions: true,
+            overflow_checks: true,
             ..Profile::default()
         }
     }
@@ -594,6 +596,7 @@ impl Default for Profile {
             rustdoc_args: None,
             debuginfo: None,
             debug_assertions: false,
+            overflow_checks: false,
             rpath: false,
             test: false,
             doc: false,
index 6ba1c8c88eca8da84ad850c2565ef7bdc0e1e4d4..b20f5709b46daa3fe9685c0170cf6c567db022d1 100644 (file)
@@ -597,8 +597,8 @@ fn build_base_args(cx: &mut Context,
                    crate_types: &[&str]) {
     let Profile {
         ref opt_level, lto, codegen_units, ref rustc_args, debuginfo,
-        debug_assertions, rpath, test, doc: _doc, run_custom_build,
-        ref panic, rustdoc_args: _, check,
+        debug_assertions, overflow_checks, rpath, test, doc: _doc,
+        run_custom_build, ref panic, rustdoc_args: _, check,
     } = *unit.profile;
     assert!(!run_custom_build);
 
@@ -678,10 +678,27 @@ fn build_base_args(cx: &mut Context,
         cmd.args(args);
     }
 
-    if debug_assertions && opt_level != "0" {
-        cmd.args(&["-C", "debug-assertions=on"]);
-    } else if !debug_assertions && opt_level == "0" {
-        cmd.args(&["-C", "debug-assertions=off"]);
+    // -C overflow-checks is implied by the setting of -C debug-assertions,
+    // so we only need to provide -C overflow-checks if it differs from
+    // the value of -C debug-assertions we would provide.
+    if opt_level != "0" {
+        if debug_assertions {
+            cmd.args(&["-C", "debug-assertions=on"]);
+            if !overflow_checks {
+                cmd.args(&["-C", "overflow-checks=off"]);
+            }
+        } else if overflow_checks {
+            cmd.args(&["-C", "overflow-checks=on"]);
+        }
+    } else {
+        if !debug_assertions {
+            cmd.args(&["-C", "debug-assertions=off"]);
+            if overflow_checks {
+                cmd.args(&["-C", "overflow-checks=on"]);
+            }
+        } else if !overflow_checks {
+            cmd.args(&["-C", "overflow-checks=off"]);
+        }
     }
 
     if test && unit.target.harness() {
index 990a7d856381603fa1a440d744893009f95ca216..084e2359b34cb1500c3522c3207cd5d4b1c0854c 100644 (file)
@@ -371,6 +371,8 @@ pub struct TomlProfile {
     debug_assertions: Option<bool>,
     rpath: Option<bool>,
     panic: Option<String>,
+    #[serde(rename = "overflow-checks")]
+    overflow_checks: Option<bool>,
 }
 
 #[derive(Clone, Debug)]
@@ -1469,7 +1471,7 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
     fn merge(profile: Profile, toml: Option<&TomlProfile>) -> Profile {
         let &TomlProfile {
             ref opt_level, lto, codegen_units, ref debug, debug_assertions, rpath,
-            ref panic
+            ref panic, ref overflow_checks,
         } = match toml {
             Some(toml) => toml,
             None => return profile,
@@ -1488,6 +1490,7 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
             rustdoc_args: None,
             debuginfo: debug.unwrap_or(profile.debuginfo),
             debug_assertions: debug_assertions.unwrap_or(profile.debug_assertions),
+            overflow_checks: overflow_checks.unwrap_or(profile.overflow_checks),
             rpath: rpath.unwrap_or(profile.rpath),
             test: profile.test,
             doc: profile.doc,
index 1eea86b5cb2c26c7e94963e6d7570a7d518c6f4b..3839d1bbd4b71940e7fdacc94137054c8404841b 100644 (file)
@@ -2535,6 +2535,7 @@ fn compiler_json_error_format() {
             "debug_assertions": true,
             "debuginfo": 2,
             "opt_level": "0",
+            "overflow_checks": true,
             "test": false
         },
         "features": [],
@@ -2574,6 +2575,7 @@ fn compiler_json_error_format() {
             "debug_assertions": true,
             "debuginfo": 2,
             "opt_level": "0",
+            "overflow_checks": true,
             "test": false
         },
         "features": [],
@@ -2593,6 +2595,7 @@ fn compiler_json_error_format() {
             "debug_assertions": true,
             "debuginfo": 2,
             "opt_level": "0",
+            "overflow_checks": true,
             "test": false
         },
         "features": [],
@@ -2620,6 +2623,7 @@ fn compiler_json_error_format() {
             "debug_assertions": true,
             "debuginfo": 2,
             "opt_level": "0",
+            "overflow_checks": true,
             "test": false
         },
         "features": [],
@@ -2679,6 +2683,7 @@ fn message_format_json_forward_stderr() {
             "debug_assertions":true,
             "debuginfo":2,
             "opt_level":"0",
+            "overflow_checks": true,
             "test":false
         },
         "features":[],
index f55c0bc988414127b50148e7df409a78d266bca2..895026d447d79815ce682945dd1625fd02d17377 100644 (file)
@@ -117,6 +117,41 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
 "));
 }
 
+#[test]
+fn cargo_test_overflow_checks() {
+    if !is_nightly() {
+        return;
+    }
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.5.0"
+            authors = []
+
+            [[bin]]
+            name = "foo"
+
+            [profile.release]
+            overflow-checks = true
+            "#)
+        .file("src/foo.rs", r#"
+            use std::panic;
+            pub fn main() {
+                let r = panic::catch_unwind(|| {
+                    [1, i32::max_value()].iter().sum::<i32>();
+                });
+                assert!(r.is_err());
+            }"#);
+
+    assert_that(p.cargo_process("build").arg("--release"),
+                execs().with_status(0));
+    assert_that(&p.release_bin("foo"), existing_file());
+
+    assert_that(process(&p.release_bin("foo")),
+                execs().with_status(0).with_stdout(""));
+}
+
 #[test]
 fn cargo_test_verbose() {
     let p = project("foo")